package operator.function;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import util.Printer;
import util.RxJavaHelper;
import util.ThreadHelper;

class RetryWhenOperator {

    static int tryTimes;

    public static void main(String[] args) {
        retryWhen();
    }

    /**
     * retryWhen和retry类似，区别是，retryWhen将onError中的Throwable传递给一个函数，这个函数产生另一个Observable
     * retryWhen观察它的结果再决定是不是要重新订阅原始的Observable
     * 如果这个Observable发射了一项数据，它就重新订阅
     * 如果这个Observable发射的是onError通知，它就将这个通知传递给观察者然后终止
     */
    static void retryWhen() {
        Observable.create(new ObservableOnSubscribe<Integer>() {

            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                if(tryTimes < 5){
                    tryTimes ++;
                    Printer.print("已经尝试了" + tryTimes + "次");
                    emitter.onError(new IllegalArgumentException());
                } else if(tryTimes == 5){
                    Printer.print("发生了其他错误");
                    emitter.onError(RxJavaHelper.getException());
                }
            }
        })
                .retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
                        return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                            @Override
                            public ObservableSource<?> apply(Throwable throwable) throws Exception {
                                if(throwable instanceof IllegalArgumentException){
                                    Printer.print("retryWhen 2秒后重试");
//                                    return Observable.timer(2, TimeUnit.SECONDS);
                                    return Observable.just(1).delay(2, TimeUnit.SECONDS);
                                } else {
                                    Printer.print("不再重试");
                                    return Observable.error(throwable);
                                }
                            }
                        });
                    }
                }).subscribe(RxJavaHelper.getConsumer());
        ThreadHelper.sleep();
    }


}
